function OSGBLodNode() {
    OSGBGroupNode.call( this );

    this.lodRanges = [];
    this.rangeDatas = [];
}

OSGBLodNode.prototype = Object.assign( Object.create( OSGBGroupNode.prototype ), {

    setModel: function (model) {
        this.setLodRanges(model.lodRanges);
        this.setRangeDatas(model.rangeDatas);
    },

    setLodRanges: function (lodRanges) {
        this.lodRanges = lodRanges;
    },

    getLodRanges: function () {
        return this.lodRanges;
    },

    setRangeDatas: function (rangeDatas) {
        this.rangeDatas = rangeDatas;
    },

    getRangeDatas: function () {
        return this.rangeDatas;
    },

    isLodGroup: function () {
        return true;
    },

    traverse: function (camera, tileset) {
        if (this.isVisible(camera)) {
            this.accept(camera, tileset);
            return true;
        }
        return false;
    },

    accept: function (camera, tileset) {
        var boundingBox = this.getWorldBoundingBox();
        var rootGeometricError = tileset.getRootGeometricError();
        var requiredRange = this.getRequiredRange(camera, boundingBox, rootGeometricError);

        var nLastChildTraversed = -1;
        var bNeedToLoadChild = false;
        for (var i = 0; i < this.lodRanges.length; i++) {
            if (this.lodRanges[i].first <= requiredRange && requiredRange < this.lodRanges[i].second) {
                if (i < this.childrens.length) {
                    var childNode = this.childrens[i];
                    var bVisible = childNode.traverse(camera, tileset);
                    nLastChildTraversed = i;

                    if (i == 0 && this.childrens.length > 1) {
                        var groupChildNode = this.childrens[1];
                        if (groupChildNode != null) {
                            this.removeChild(groupChildNode);
                            this.releaseChild(groupChildNode, tileset);
                        }
                    } else if (i == 1 && !bVisible) {
                        if (childNode != null) {
                            this.removeChild(childNode);
                            this.releaseChild(childNode, tileset);
                        }
                    }
                } else {
                    bNeedToLoadChild = true;
                }
            }
        }

        if (bNeedToLoadChild) {
            var nChildrenCount = this.childrens.length;
            if (nChildrenCount > 0 && (nChildrenCount - 1) != nLastChildTraversed) {
                var childNode = this.childrens[nChildrenCount - 1];
                if (childNode.isGeoNode()) {
                    var k = 0;
                }
                var bVisible = childNode.traverse(camera, tileset);
                if (!bVisible) {
                    if (childNode.isGroup()) {
                        this.removeChild(childNode);
                        this.releaseChild(childNode, tileset);
                    }
                }
            }

            if (nChildrenCount < this.rangeDatas.length) {
                if (this.getState() == OSGBNodeState.UnLoad) {
                    this.setState(OSGBNodeState.Loading);
                    var strKey = this.getRoot().getName() + "/" + this.rangeDatas[nChildrenCount];
                    tileset.requestTask(this.getName(), strKey, this);
                }
            }
        }
    },

    release: function () {
        this.lodRanges.length = 0;
        this.rangeDatas.length = 0;
        OSGBGroupNode.prototype.release.call(this);
    },

    getRequiredRange: function (camera, boundingBox, rootGeometricError) {
        var c1 = new THREE.Vector3(0,0,0);
        var center = boundingBox.getCenter(c1);
        let size = new THREE.Vector2(0,0);
        var radius = boundingBox.getSize(size).length() * 0.5;
        return camera.clampedPixelSize(center, radius, rootGeometricError);
    },

} );
